/*
 * @(#)HibernateTranslator.java    Jul 30, 2010
 *
 * Copyright 2009 Nyber(Shanghai Itd. All rights reserved.
 */

package com.common.util;

import java.util.Collections;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.hql.QueryTranslator;
import org.hibernate.hql.QueryTranslatorFactory;
import org.hibernate.hql.ast.ASTQueryTranslatorFactory;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.impl.SessionImpl;
import org.hibernate.loader.criteria.CriteriaJoinWalker;
import org.hibernate.loader.criteria.CriteriaQueryTranslator;
import org.hibernate.persister.entity.OuterJoinLoadable;

/**
 * A helper-class to transform HQL or Criteria to SQL.
 *
 * @author nickevin@gmail.com
 * @version Jul 30, 2010 10:22:28 AM
 */

public class HibernateSqlTranslator {

	private HibernateSqlTranslator() {}

	public static String getSqlString(Session session, DetachedCriteria criteria) {
		try {
			return toSql((CriteriaImpl) criteria.getExecutableCriteria(session));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static String getSqlString(Criteria criteria) {
		try {
			return toSql((CriteriaImpl) criteria);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private static String toSql(CriteriaImpl criteriaImpl) {
		SessionImpl sessionImp = (SessionImpl) criteriaImpl.getSession();
		SessionFactoryImplementor factory = (SessionFactoryImplementor) sessionImp
				.getSessionFactory();
		String[] implementors = factory.getImplementors(criteriaImpl
				.getEntityOrClassName());
		CriteriaQueryTranslator translator = new CriteriaQueryTranslator(
				factory, criteriaImpl, implementors[0],
				CriteriaQueryTranslator.ROOT_SQL_ALIAS);
		OuterJoinLoadable persister = (OuterJoinLoadable) factory
				.getEntityPersister(implementors[0]);
		CriteriaJoinWalker walker = new CriteriaJoinWalker(persister,
				translator, factory, criteriaImpl, implementors[0], sessionImp
						.getLoadQueryInfluencers());

		return walker.getSQLString();
	}

	public static String getSqlString(SessionFactory sessionFactory, String hql) {
		if (hql == null || hql.length() == 0) {
			throw new IllegalArgumentException(
					"hql can not null object or empty content.");
		}

		QueryTranslatorFactory translatorFactory = new ASTQueryTranslatorFactory();
		SessionFactoryImplementor factory = (SessionFactoryImplementor) sessionFactory;
		QueryTranslator translator = translatorFactory.createQueryTranslator(
				hql, hql, Collections.EMPTY_MAP, factory);
		translator.compile(Collections.EMPTY_MAP, false);

		return translator.getSQLString();
	}
}